#pragma once
#include <stdlib.h>
#include <stdint.h>
#include "double_list.h"

struct MemBlock 
{
	uint32_t   free_idx;
	uint32_t   free_num;
	void*      free_list;
	DoubleNode block_list;

	MemBlock()
		: free_idx(0),
		free_num(0),
		free_list(NULL),
		block_list(reinterpret_cast<void*>(this))
	{}
};

class ChunkPool
{
public:
	ChunkPool(uint32_t reserve_size,
			  uint32_t chunk_size,
              uint32_t chunk_count,
              bool free_to_sys);
	virtual ~ChunkPool();

	void* AllocChunk();
	bool  FreeChunk(void* chunk);

	uint32_t ChunkSize()
	{
		return chunk_size_;
	}

protected:
	MemBlock* AllocBlock();
	void*  AllocChunk(MemBlock* block);
	bool   FreeChunk(MemBlock* block, void* chunk);
	void   FreeBlockList(DoubleList& list);
	void*& NextOf(void* const chunk);

protected:
	bool        free_to_sys_;
	uint32_t    reserve_size_;
	uint32_t    chunk_size_;
	uint32_t    chunk_count_;
	uint32_t    free_count_;
	uint32_t    free_threshold_;
	size_t      mem_size_;
	DoubleList  block_list_;
	DoubleList  empty_list_;
	DoubleList  full_list_;
};

#ifndef  CHECK_MEM_LEAK
#define  CHECK_MEM_LEAK
#endif // CHECK_MEM_LEAK